#include "utilities.h"
#include "CBuilding.h"
#include "CCamera.h"
#include "CCar.h"
#include "CEventReceiver.h"
#include "CMainMenu.h"
#include "CRandom.h"
#include "CRoad.h"
#include "CSpeedometer.h"
#include <time.h>


// Time delay before key input will repeat
#define KEYBOARD_DELAY	400


int main()
{
	// Ask user for driver
	//E_DRIVER_TYPE driverType = driverChoiceConsole();
	
	//if (driverType == EDT_COUNT) return 1;
		
	CEventReceiver receiver;

	// Create device
	IrrlichtDevice* device = createDevice(/*driverType*/EDT_OPENGL,	
		dimension2du(800, 600), 16, false, false, false, &receiver);

	if (!device) return 1;
			
	device->setWindowCaption(L"Car Racing - Irrlicht Engine");
	device->getCursorControl()->setVisible(false);

	// Pointers to the main objects
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

	enum GAME_STATE {MAIN_MENU = 0, PLAY, PAUSE};
	int gameState = MAIN_MENU;

	u32 playerCarIndex	= 1;
	u32 carsNumber		= 4;
	u32 buildingsNumber = 20;

	// Road
	CRoad road = CRoad(device); 

	// Buildings
	CBuilding building = CBuilding(device, buildingsNumber);
	
	// Cars
	array<CCar> car;
	for (u32 i = 0; i < carsNumber; ++i)
	{
		car.push_back(CCar(device, 0.45f));
		car.getLast().setPosition(vector3df(ROAD_WIDTH * (i + 1)/(carsNumber + 1), CAR_POS_Y, 16.f));
	}

	car[playerCarIndex].setMaxSpeed(0.5f);

	// Camera
	CCamera camera = CCamera(smgr, car[playerCarIndex]);

	// Main menu
	CMainMenu mainMenu = CMainMenu(device);

	// Speedometer
	CSpeedometer speedometer = CSpeedometer(device, vector2di(
		driver->getScreenSize().Width - 160, driver->getScreenSize().Height - 160));

	// Font
	IGUIFont* font = device->getGUIEnvironment()->getBuiltInFont();

	int accelDir = CCar::ACCEL_NO;
	int turnDir = CCar::TURN_NO;

	u32 refreshTimer = 0;
	u32 keyboardTimer = 0;

	while (device->run())
	{
		if (device->isWindowActive())
		{
			driver->beginScene();

			switch (gameState)
			{
			case MAIN_MENU:
				{
					if(receiver.isKeyDown(KEY_UP) && 
						(device->getTimer()->getTime() - keyboardTimer) > KEYBOARD_DELAY)
					{
						keyboardTimer = device->getTimer()->getTime();
						mainMenu.cursorUp();
					}
					
					if(receiver.isKeyDown(KEY_DOWN) && 
						(device->getTimer()->getTime() - keyboardTimer) > KEYBOARD_DELAY)
					{
						keyboardTimer = device->getTimer()->getTime();
						mainMenu.cursorDown();
					}

					if(receiver.isKeyDown(KEY_RETURN))
					{
						keyboardTimer = device->getTimer()->getTime();
						
						switch (mainMenu.getSelectedItem())
						{
						case CMainMenu::PLAY:
							{
								gameState = PLAY;
								break;
							}
						case CMainMenu::EXIT:
							{
								device->closeDevice();
								break;
							}
						default: break;
						}
					}

					mainMenu.update();
					break;
				}
			case PLAY:
				{
					if ((device->getTimer()->getTime() - refreshTimer) > 10)	
					{
						refreshTimer = device->getTimer()->getTime();

						for (u32 i = 0; i < carsNumber; ++i)
						{
							if (i != playerCarIndex)
							{ 
								// NPC car
								accelDir = CCar::ACCEL_FRWD;
								turnDir = car[i].genTurn(vector3df(ROAD_WIDTH/2, 0.f, 1600.f));
							}
							else
							{ 
								// Player car
								if (receiver.isKeyDown(KEY_KEY_W))
								{
									accelDir = CCar::ACCEL_FRWD;
								}
								if (receiver.isKeyDown(KEY_KEY_S)) 
								{
									accelDir = CCar::ACCEL_BCKWD;
								}
								if (receiver.isKeyDown(KEY_KEY_A))
								{
									turnDir = CCar::TURN_LEFT;
								}
								if (receiver.isKeyDown(KEY_KEY_D)) 
								{
									turnDir = CCar::TURN_RIGHT;
								}
								if(!receiver.isKeyDown(KEY_KEY_W) &&
									!receiver.isKeyDown(KEY_KEY_S))
								{
									accelDir = CCar::ACCEL_NO;
								}
								if(!receiver.isKeyDown(KEY_KEY_A) &&
									!receiver.isKeyDown(KEY_KEY_D))
								{
									turnDir = CCar::TURN_NO;
								}

								printf("%f\n", abs(car[i].getNode()->getRotation().Y - 180));

								speedometer.rotateArrow(-abs(car[i].getSpeed()) / car[i].getMaxSpeed() * 270);
							}
					
							car[i].update(accelDir, turnDir);
							
							// Check collisions between cars
							for (u32 j = i + 1; j < carsNumber; ++j)
							{
								car[i].checkCollision(car[j].getNode());
							}
							
							// Check collisions between cars and buildings
							for (u32 j = 0; j < buildingsNumber; ++j)
							{
								car[i].checkCollision(building.getNode(j));
							}

							// Change camera view on key 'C'
							if((receiver.isKeyDown(KEY_KEY_C)) && 
								(device->getTimer()->getTime() - keyboardTimer) > KEYBOARD_DELAY)
							{
								keyboardTimer = device->getTimer()->getTime();
								camera.switchCam();
							}
						} // for (u32 i = 1; i < carsNumber; ++i)
				
						camera.update();

						// Quit game on key 'Q'
						if (receiver.isKeyDown(KEY_KEY_Q))
						{
							device->closeDevice();
						}

						// Pause mode on key 'Esc'
						if (receiver.isKeyDown(KEY_ESCAPE) && 
							(device->getTimer()->getTime() - keyboardTimer) > KEYBOARD_DELAY)
						{
							keyboardTimer = device->getTimer()->getTime();
							gameState = PAUSE;
						}
					} // ((device->getTimer()->getTime() - refreshTime) > 10)
					
					smgr->drawAll();
					speedometer.update();

					// Show help info
					font->draw("C - change camera view\nEscape - pause game\nQ - exit game",
					recti(10, 10, 0, 0), SColor(255, 255, 255, 255), false, false, 0);

					break;
				} // case PLAY:
			case PAUSE:
				{
					// Return to play mode on KEY_ESCAPE
					if((receiver.isKeyDown(KEY_ESCAPE)) && 
						(device->getTimer()->getTime() - keyboardTimer) > KEYBOARD_DELAY)
					{
						keyboardTimer = device->getTimer()->getTime();
						gameState = PLAY;
					}

					// Redraw all scene nodes and show 'Pause' on top of them
					smgr->drawAll();
					mainMenu.drawPause();
					
					break;
				}
			} // switch (gameState)

			driver->endScene();
		} //if (device->isWindowActive())
	} // while (device->run())

	device->drop();
	
	return 0;
}